home *** CD-ROM | disk | FTP | other *** search
/ Shareware Grab Bag / Shareware Grab Bag.iso / 001 / pibt40s2.arc / PIBASYN3.MOD < prev    next >
Text File  |  1987-09-05  |  46KB  |  854 lines

  1. (*----------------------------------------------------------------------*)
  2. (* Async_Find_Delay  --- Finds delay loop value for 1 millesecond delay *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Find_Delay( VAR One_MS_Delay : INTEGER );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*      Procedure: Async_Find_Delay                                     *)
  10. (*                                                                      *)
  11. (*      Purpose:   Finds loop count value to effect 1 ms delay          *)
  12. (*                                                                      *)
  13. (*      Calling Sequence:                                               *)
  14. (*                                                                      *)
  15. (*         Async_Find_Delay( VAR One_MS_Delay : INTEGER );              *)
  16. (*                                                                      *)
  17. (*            One_MS_Delay --- Resulting loop count for 1 ms delay      *)
  18. (*                                                                      *)
  19. (*      Using result:                                                   *)
  20. (*                                                                      *)
  21. (*            Use loop of form:                                         *)
  22. (*                                                                      *)
  23. (*                      MOV    CX,[>One_MS_Delay]                       *)
  24. (*               Delay: LOOP   Delay                                    *)
  25. (*                                                                      *)
  26. (*            to delay for 1 ms.                                        *)
  27. (*                                                                      *)
  28. (*      Remarks:                                                        *)
  29. (*                                                                      *)
  30. (*         This routine watches over the CPU elapsed timer value for    *)
  31. (*         just one timer interval (55 milleseconds).  During that time *)
  32. (*         we run a tight loop and accumulate the ticks.  The result    *)
  33. (*         is the number of ticks required for a 55 ms delay.  The      *)
  34. (*         ticks for a 1 ms delay = ( ticks for 55 ms ) / 55.           *)
  35. (*                                                                      *)
  36. (*         To avoid overflow problems on fast machines, and to ease the *)
  37. (*         worry about storing results at the second timer tick, we     *)
  38. (*         break up the single long tight loop into a series of short   *)
  39. (*         loops inside an outer loop.  We check if the timer has       *)
  40. (*         expired at the end of each inner short loop.  Then the       *)
  41. (*         time for the 55 ms delay is:                                 *)
  42. (*                                                                      *)
  43. (*            Ticks_for_55 := Inner_Ticks * Outer_Ticks;                *)
  44. (*                                                                      *)
  45. (*         and the corresponding 1 ms delay is:                         *)
  46. (*                                                                      *)
  47. (*            Ticks_For_1  := Ticks_For_55 DIV 55;                      *)
  48. (*                                                                      *)
  49. (*         To simplify things, we choose the inner tick value to be     *)
  50. (*         2 x 55 = 110.  Then:                                         *)
  51. (*                                                                      *)
  52. (*            Ticks_For_1  := ( 110 * Outer_Ticks ) / 55;  ==>          *)
  53. (*            Ticks_For_1  := 2 * Outer_Ticks;                          *)
  54. (*                                                                      *)
  55. (*         The CPU timer is located in four bytes at $0000:$46C.        *)
  56. (*         Interrupt $1A also returns these bytes, but using the        *)
  57. (*         interrupt results in an inaccurate loop count value.         *)
  58. (*                                                                      *)
  59. (*         The local variables used here were moved to the data segment *)
  60. (*         since I couldn't get Turbo to generate the correct offsets   *)
  61. (*         otherwise.                                                   *)
  62. (*                                                                      *)
  63. (*         Thanks to Brian Foley and Kim Kokonnen for help with this    *)
  64. (*         problem.                                                     *)
  65. (*                                                                      *)
  66. (*----------------------------------------------------------------------*)
  67.  
  68. (* STRUCTURED *) CONST
  69.    Hi_Timer         : INTEGER = 0  (* Saves high portion of timer        *);
  70.    Lo_Timer         : INTEGER = 0  (* Saves low portion of timer         *);
  71.    OutCount         : INTEGER = 0  (* Accumulates outer loop counts      *);
  72.  
  73. BEGIN (* Async_Find_Delay *)
  74.  
  75. INLINE(
  76.   $1E                       {          PUSH   DS                    ;Save DS}
  77.                             {;}
  78.   /$8C/$C8                  {          MOV    AX,CS}
  79.   /$8E/$D8                  {          MOV    DS,AX                 ;Allow access to local variables}
  80.                             {;}
  81.   /$31/$C0                  {          XOR    AX,AX                 ;Clear AX to zero}
  82.   /$8E/$C0                  {          MOV    ES,AX                 ;Allow low-memory access}
  83.                             {;}
  84.   /$C7/$06/>OUTCOUNT/$00/$00{          MOV    WORD [>OutCount],0    ;Clear outer loop counter}
  85.                             {;}
  86.   /$FA                      {          CLI                          ;No interrupts while reading}
  87.   /$26/$8B/$0E/>$46E        {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  88.   /$26/$8B/$16/>$46C        {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  89.   /$FB                      {          STI                          ;Interrupts back on}
  90.                             {;}
  91.   /$89/$0E/>HI_TIMER        {          MOV    [>Hi_Timer],CX        ;Save hi part of timer}
  92.   /$89/$16/>LO_TIMER        {          MOV    [>Lo_Timer],DX        ;Save low part of timer}
  93.                             {;}
  94.   /$FA                      {Loop1:    CLI                          ;No interrupts while reading}
  95.                             {;}
  96.   /$26/$8B/$0E/>$46E        {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  97.   /$26/$8B/$16/>$46C        {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  98.                             {;}
  99.   /$FB                      {          STI                          ;Interrupts back on}
  100.                             {;}
  101.   /$89/$C8                  {          MOV    AX,CX                 ;Save CX and DX for later}
  102.   /$89/$D3                  {          MOV    BX,DX}
  103.                             {;}
  104.   /$2B/$06/>HI_TIMER        {          SUB    AX,[>Hi_Timer]        ;Subtract low order part}
  105.   /$1B/$1E/>LO_TIMER        {          SBB    BX,[>Lo_Timer]        ;Subtract high order part}
  106.                             {;}
  107.   /$74/$E6                  {          JE     Loop1                 ;Continue until non-0 tick difference}
  108.                             {;}
  109.   /$89/$0E/>HI_TIMER        {          MOV    [>Hi_Timer],CX        ;Save hi part}
  110.   /$89/$16/>LO_TIMER        {          MOV    [>Lo_Timer],DX        ;Save low part}
  111.                             {;}
  112.   /$B9/$6E/$00              {Loop2:    MOV    CX,110                ;Run short delay loop.}
  113.   /$E2/$FE                  {Delay:    LOOP   Delay}
  114.                             {;}
  115.   /$FA                      {          CLI                          ;No interrupts while reading}
  116.                             {;}
  117.   /$26/$8B/$0E/>$46E        {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  118.   /$26/$8B/$16/>$46C        {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  119.                             {;}
  120.   /$FB                      {          STI                          ;Interrupts back on}
  121.                             {;}
  122.   /$FF/$06/>OUTCOUNT        {          INC    WORD [>OutCount]      ;Increment outer loop count}
  123.                             {;}
  124.   /$2B/$0E/>HI_TIMER        {          SUB    CX,[>Hi_Timer]        ;Subtract low order part}
  125.   /$1B/$16/>LO_TIMER        {          SBB    DX,[>Lo_Timer]        ;Subtract high order part}
  126.                             {;}
  127.   /$74/$E1                  {          JE     Loop2                 ;Keep going if next tick not found}
  128.                             {;}
  129.   /$A1/>OUTCOUNT            {          MOV    AX,[>OutCount]        ;Pick up outer loop counter}
  130.   /$D1/$E0                  {          SHL    AX,1                  ;* 2 = ticks for 1 ms delay}
  131.                             {;}
  132.   /$C4/$BE/>ONE_MS_DELAY    {          LES    DI,[BP+>One_MS_Delay] ;Get address of result}
  133.   /$26/$89/$05              {      ES: MOV    [DI],AX               ;Store result}
  134.                             {;}
  135.   /$1F                      {          POP    DS                    ;Restore data segment register}
  136. );
  137.  
  138. END   (* Async_Find_Delay *);
  139.  
  140. (*----------------------------------------------------------------------*)
  141. (*               Async_Init --- Initialize Asynchronous Variables       *)
  142. (*----------------------------------------------------------------------*)
  143.  
  144. PROCEDURE Async_Init( Async_Buffer_Max  : INTEGER;
  145.                       Async_OBuffer_Max : INTEGER;
  146.                       Async_High_Lev1   : INTEGER;
  147.                       Async_High_Lev2   : INTEGER;
  148.                       Async_Low_Lev     : INTEGER );
  149.  
  150. (*----------------------------------------------------------------------*)
  151. (*                                                                      *)
  152. (*     Procedure:  Async_Init                                           *)
  153. (*                                                                      *)
  154. (*     Purpose:    Initializes variables                                *)
  155. (*                                                                      *)
  156. (*     Calling Sequence:                                                *)
  157. (*                                                                      *)
  158. (*         Async_Init( Async_Buffer_Max  : INTEGER;                     *)
  159. (*                     Async_OBuffer_Max : INTEGER;                     *)
  160. (*                     Async_High_Lev1   : INTEGER;                     *)
  161. (*                     Async_High_Lev2   : INTEGER;                     *)
  162. (*                     Async_Low_Lev     : INTEGER );                   *)
  163. (*                                                                      *)
  164. (*     Calls:  Async_Find_Delay                                         *)
  165. (*             TurnOffTimeSharing                                       *)
  166. (*             TurnOnTimeSharing                                        *)
  167. (*                                                                      *)
  168. (*----------------------------------------------------------------------*)
  169.  
  170. VAR
  171.    I: INTEGER;
  172.  
  173. (*----------------------------------------------------------------------*)
  174.  
  175. BEGIN   (* Async_Init *)
  176.                                    (* Save data segment address in code *)
  177.                                    (* segment for use in serial port    *)
  178.                                    (* interrupt handler.                *)
  179.    Async_DSeg_Save        := DSeg;
  180.  
  181.                                    (* No port open yet.                 *)
  182.    Async_Open_Flag        := FALSE;
  183.  
  184.                                    (* No XON/XOFF handling yet.         *)
  185.    Async_XOFF_Sent        := FALSE;
  186.    Async_XOFF_Received    := FALSE;
  187.    Async_XOFF_Rec_Display := FALSE;
  188.    Async_XON_Rec_Display  := FALSE;
  189.    Async_Send_XOFF        := FALSE;
  190.    Async_Send_Address     := 0;
  191.  
  192.                                    (* Set up empty receive buffer       *)
  193.    Async_Buffer_Overflow  := FALSE;
  194.    Async_Buffer_Used      := 0;
  195.    Async_MaxBufferUsed    := 0;
  196.    Async_Buffer_Head      := 0;
  197.    Async_Buffer_Tail      := 0;
  198.                                    (* Set up empty send buffer.         *)
  199.    Async_OBuffer_Overflow := FALSE;
  200.    Async_OBuffer_Used     := 0;
  201.    Async_MaxOBufferUsed   := 0;
  202.    Async_OBuffer_Head     := 0;
  203.    Async_OBuffer_Tail     := 0;
  204.                                    (* Set default wait time for output   *)
  205.                                    (* buffer to drain when it fills up.  *)
  206.    Async_Output_Delay     := 500;
  207.  
  208.                                    (* No modem or line errors yet.       *)
  209.    Async_Line_Status      := 0;
  210.    Async_Modem_Status     := 0;
  211.    Async_Line_Error_Flags := 0;
  212.  
  213.                                    (* Get buffer sizes *)
  214.  
  215.    IF ( Async_Buffer_Max > 0 ) THEN
  216.       Async_Buffer_Size := Async_Buffer_Max  - 1
  217.    ELSE
  218.       Async_Buffer_Size := 4095;
  219.  
  220.    IF ( Async_OBuffer_Max > 0 ) THEN
  221.       Async_OBuffer_Size := Async_OBuffer_Max - 1
  222.    ELSE
  223.       Async_OBuffer_Size := 1131;
  224.  
  225.                                    (* Get receive buffer overflow *)
  226.                                    (* check-points.               *)
  227.    IF ( Async_Low_Lev > 0 ) THEN
  228.       Async_Buffer_Low := Async_Low_Lev
  229.    ELSE
  230.       Async_Buffer_Low := Async_Buffer_Size DIV 4;
  231.  
  232.    IF ( Async_High_Lev1 > 0 ) THEN
  233.       Async_Buffer_High := Async_High_Lev1
  234.    ELSE
  235.       Async_Buffer_High := ( Async_Buffer_Size DIV 4 ) * 3;
  236.  
  237.    IF ( Async_High_Lev2 > 0 ) THEN
  238.       Async_Buffer_High_2 := Async_High_Lev2
  239.    ELSE
  240.       Async_Buffer_High_2 := ( Async_Buffer_Size DIV 10 ) * 9;
  241.  
  242.                                    (* Allocate buffers *)
  243.  
  244.    GETMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  245.    GETMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  246.  
  247.                                    (* No UART addresses defined yet *)
  248.    Async_Uart_IER         := 0;
  249.    Async_Uart_IIR         := 0;
  250.    Async_Uart_MSR         := 0;
  251.    Async_Uart_LSR         := 0;
  252.                                    (* Set default port addresses *)
  253.                                    (* and default IRQ lines      *)
  254.    FOR I := 1 TO MaxComPorts DO
  255.       BEGIN
  256.          Com_Base[I]  := Default_Com_Base [I];
  257.          Com_Irq [I]  := Default_Com_Irq  [I];
  258.          Com_RS232[I] := Default_Com_RS232[I];
  259.       END;
  260.                                    (* Get the delay loop value for 1 ms *)
  261.                                    (* delay loops.                      *)
  262.    IF TimeSharingActive THEN
  263.       TurnOffTimeSharing;
  264.  
  265.    Async_Find_Delay( Async_OneMSDelay );
  266.  
  267.    IF TimeSharingActive THEN
  268.       TurnOnTimeSharing;
  269.  
  270. END     (* Async_Init *);
  271.  
  272. (*----------------------------------------------------------------------*)
  273. (*      Async_Carrier_Detect --- Check for modem carrier detect         *)
  274. (*----------------------------------------------------------------------*)
  275.  
  276. FUNCTION Async_Carrier_Detect : BOOLEAN;
  277.  
  278. (*----------------------------------------------------------------------*)
  279. (*                                                                      *)
  280. (*     Function:   Async_Carrier_Detect                                 *)
  281. (*                                                                      *)
  282. (*     Purpose:    Looks for modem carrier detect                       *)
  283. (*                                                                      *)
  284. (*     Calling Sequence:                                                *)
  285. (*                                                                      *)
  286. (*        Flag := Async_Carrier_Detect : BOOLEAN;                       *)
  287. (*                                                                      *)
  288. (*           Flag is set TRUE if carrier detected, else FALSE.          *)
  289. (*                                                                      *)
  290. (*     Calls:  None                                                     *)
  291. (*                                                                      *)
  292. (*----------------------------------------------------------------------*)
  293.  
  294. BEGIN (* Async_Carrier_Detect *)
  295.  
  296.    Async_Carrier_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  297.                            Async_Hard_Wired_On;
  298.  
  299. END   (* Async_Carrier_Detect *);
  300.  
  301. (*----------------------------------------------------------------------*)
  302. (*      Async_Carrier_Drop --- Check for modem carrier drop/timeout     *)
  303. (*----------------------------------------------------------------------*)
  304.  
  305. FUNCTION Async_Carrier_Drop : BOOLEAN;
  306.  
  307. (*----------------------------------------------------------------------*)
  308. (*                                                                      *)
  309. (*     Function:   Async_Carrier_Drop                                   *)
  310. (*                                                                      *)
  311. (*     Purpose:    Looks for modem carrier drop/timeout                 *)
  312. (*                                                                      *)
  313. (*     Calling Sequence:                                                *)
  314. (*                                                                      *)
  315. (*        Flag := Async_Carrier_Drop : BOOLEAN;                         *)
  316. (*                                                                      *)
  317. (*           Flag is set TRUE if carrier dropped, else FALSE.           *)
  318. (*                                                                      *)
  319. (*     Calls:  None                                                     *)
  320. (*                                                                      *)
  321. (*----------------------------------------------------------------------*)
  322.  
  323. BEGIN (* Async_Carrier_Drop *)
  324.  
  325.    Async_Carrier_Drop := NOT ( ODD( Port[ UART_MSR + Async_Base ] SHR 7 ) OR
  326.                                Async_Hard_Wired_On );
  327.  
  328. END   (* Async_Carrier_Drop *);
  329.  
  330. (*----------------------------------------------------------------------*)
  331. (*      Async_Term_Ready --- Set terminal ready status                  *)
  332. (*----------------------------------------------------------------------*)
  333.  
  334. PROCEDURE Async_Term_Ready( Ready_Status : BOOLEAN );
  335.  
  336. (*----------------------------------------------------------------------*)
  337. (*                                                                      *)
  338. (*     Procedure:  Async_Term_Ready                                     *)
  339. (*                                                                      *)
  340. (*     Purpose:    Sets terminal ready status                           *)
  341. (*                                                                      *)
  342. (*     Calling Sequence:                                                *)
  343. (*                                                                      *)
  344. (*        Async_Term_Ready( Ready_Status : BOOLEAN );                   *)
  345. (*                                                                      *)
  346. (*           Ready_Status --- Set TRUE to set terminal ready on,        *)
  347. (*                            Set FALSE to set terminal ready off.      *)
  348. (*                                                                      *)
  349. (*     Calls:  None                                                     *)
  350. (*                                                                      *)
  351. (*----------------------------------------------------------------------*)
  352.  
  353. VAR
  354.    Mcr_Value: BYTE;
  355.  
  356. BEGIN (* Async_Term_Ready *)
  357.  
  358.    Mcr_Value := ( PORT[ UART_MCR + Async_Base ] AND $FE );
  359.  
  360.    IF Ready_Status THEN
  361.       Mcr_Value := Mcr_Value OR 1;
  362.  
  363.    PORT[ UART_MCR + Async_Base ] := Mcr_Value;
  364.  
  365.    Async_Clear_Errors;
  366.  
  367. END   (* Async_Term_Ready *);
  368.  
  369. (*----------------------------------------------------------------------*)
  370. (*          Async_Buffer_Check --- Check if character in buffer         *)
  371. (*----------------------------------------------------------------------*)
  372.  
  373. FUNCTION Async_Buffer_Check : BOOLEAN;
  374.  
  375. (*----------------------------------------------------------------------*)
  376. (*                                                                      *)
  377. (*     Function:   Async_Buffer_Check                                   *)
  378. (*                                                                      *)
  379. (*     Purpose:    Check if character in buffer                         *)
  380. (*                                                                      *)
  381. (*     Calling Sequence:                                                *)
  382. (*                                                                      *)
  383. (*        Flag := Async_Buffer_Check : BOOLEAN;                         *)
  384. (*                                                                      *)
  385. (*           Flag returned TRUE if character received in buffer,        *)
  386. (*           Flag returned FALSE if no character received.              *)
  387. (*                                                                      *)
  388. (*     Calls:  None                                                     *)
  389. (*                                                                      *)
  390. (*     Remarks:                                                         *)
  391. (*                                                                      *)
  392. (*       This routine only checks if a character has been received      *)
  393. (*       and thus can be read; it does NOT return the character.        *)
  394. (*       Use Async_Receive to read the character.                       *)
  395. (*                                                                      *)
  396. (*----------------------------------------------------------------------*)
  397.  
  398. BEGIN   (* Async_Buffer_Check *)
  399.  
  400.    Async_Buffer_Check := ( Async_Buffer_Head <> Async_Buffer_Tail );
  401.  
  402. END     (* Async_Buffer_Check *);
  403.  
  404. (*----------------------------------------------------------------------*)
  405. (*          Async_Line_Error --- Check if line status error occurred    *)
  406. (*----------------------------------------------------------------------*)
  407.  
  408. FUNCTION Async_Line_Error( VAR Error_Flags: BYTE ) : BOOLEAN;
  409.  
  410. (*----------------------------------------------------------------------*)
  411. (*                                                                      *)
  412. (*     Function:   Async_Line_Error                                     *)
  413. (*                                                                      *)
  414. (*     Purpose:    Check if line status error occurred                  *)
  415. (*                                                                      *)
  416. (*     Calling Sequence:                                                *)
  417. (*                                                                      *)
  418. (*        Flag := Async_Line_Error(VAR Error_Flags: BYTE): BOOLEAN;   *)
  419. (*                                                                      *)
  420. (*           Error_Flags --- Current error flags                        *)
  421. (*                                                                      *)
  422. (*           Flag returned TRUE if line status error occurred,          *)
  423. (*           Flag returned FALSE if no error.                           *)
  424. (*                                                                      *)
  425. (*     Calls:  None                                                     *)
  426. (*                                                                      *)
  427. (*     Remarks:                                                         *)
  428. (*                                                                      *)
  429. (*        The line status error flag is cleared here.                   *)
  430. (*                                                                      *)
  431. (*----------------------------------------------------------------------*)
  432.  
  433. BEGIN   (* Async_Line_Error *)
  434.  
  435.    Async_Line_Error       := ( Async_Line_Error_Flags <> 0 );
  436.    Error_Flags            := Async_Line_Error_Flags;
  437.    Async_Line_Error_Flags := 0;
  438.  
  439. END     (* Async_Line_Error  *);
  440.  
  441. (*----------------------------------------------------------------------*)
  442. (*            Async_Ring_Detect --- Check for phone ringing             *)
  443. (*----------------------------------------------------------------------*)
  444.  
  445. FUNCTION Async_Ring_Detect : BOOLEAN;
  446.  
  447. (*----------------------------------------------------------------------*)
  448. (*                                                                      *)
  449. (*     Function:   Async_Ring_Detect                                    *)
  450. (*                                                                      *)
  451. (*     Purpose:    Looks for phone ringing                              *)
  452. (*                                                                      *)
  453. (*     Calling Sequence:                                                *)
  454. (*                                                                      *)
  455. (*        Flag := Async_Ring_Detect : BOOLEAN;                          *)
  456. (*                                                                      *)
  457. (*           Flag is set TRUE if ringing detected, else FALSE.          *)
  458. (*                                                                      *)
  459. (*     Calls:  None                                                     *)
  460. (*                                                                      *)
  461. (*----------------------------------------------------------------------*)
  462.  
  463. BEGIN (* Async_Ring_Detect *)
  464.  
  465.    Async_Ring_Detect := ODD( Port[ UART_MSR + Async_Base ] SHR 6 );
  466.  
  467. END   (* Async_Ring_Detect *);
  468.  
  469. (*----------------------------------------------------------------------*)
  470. (*          Async_Send_Break --- Send break (attention) signal          *)
  471. (*----------------------------------------------------------------------*)
  472.  
  473. PROCEDURE Async_Send_Break;
  474.  
  475. (*----------------------------------------------------------------------*)
  476. (*                                                                      *)
  477. (*     Procedure:  Async_Send_Break                                     *)
  478. (*                                                                      *)
  479. (*     Purpose:    Sends break signal over communications port          *)
  480. (*                                                                      *)
  481. (*     Calling Sequence:                                                *)
  482. (*                                                                      *)
  483. (*        Async_Send_Break;                                             *)
  484. (*                                                                      *)
  485. (*     Calls:  None                                                     *)
  486. (*                                                                      *)
  487. (*----------------------------------------------------------------------*)
  488.  
  489. VAR
  490.    Old_Lcr   : BYTE;
  491.    Break_Lcr : BYTE;
  492.  
  493. BEGIN (* Async_Send_Break *)
  494.  
  495.    Old_Lcr   := Port[ UART_LCR + Async_Base ];
  496.    Break_Lcr := Old_Lcr;
  497.  
  498.    IF Break_Lcr >  127 THEN Break_Lcr := Break_Lcr - 128;
  499.    IF Break_Lcr <=  63 THEN Break_Lcr := Break_Lcr +  64;
  500.  
  501.    Port[ UART_LCR + Async_Base ] := Break_Lcr;
  502.  
  503.    DELAY( Async_Break_Length * 10 );
  504.  
  505.    Port[ UART_LCR + Async_Base ] := Old_Lcr;
  506.  
  507. END   (* Async_Send_Break *);
  508.  
  509. (*----------------------------------------------------------------------*)
  510. (*     Async_Send_String --- Send string over communications port       *)
  511. (*----------------------------------------------------------------------*)
  512.  
  513. PROCEDURE Async_Send_String( S : AnyStr );
  514.  
  515. (*----------------------------------------------------------------------*)
  516. (*                                                                      *)
  517. (*     Procedure:  Async_Send_String                                    *)
  518. (*                                                                      *)
  519. (*     Purpose:    Sends string out over communications port            *)
  520. (*                                                                      *)
  521. (*     Calling Sequence:                                                *)
  522. (*                                                                      *)
  523. (*        Async_Send_String( S : AnyStr );                              *)
  524. (*                                                                      *)
  525. (*           S --- String to send                                       *)
  526. (*                                                                      *)
  527. (*     Calls:  Async_Send                                               *)
  528. (*                                                                      *)
  529. (*----------------------------------------------------------------------*)
  530.  
  531. VAR
  532.    I : INTEGER;
  533.  
  534. BEGIN  (* Async_Send_String *)
  535.  
  536.   FOR I := 1 TO LENGTH( S ) DO
  537.      Async_Send( S[I] )
  538.  
  539. END    (* Async_Send_String *);
  540.  
  541. (*----------------------------------------------------------------------*)
  542. (*     Async_Send_String_With_Delays --- Send string with timed delays  *)
  543. (*----------------------------------------------------------------------*)
  544.  
  545. PROCEDURE Async_Send_String_With_Delays( S          : AnyStr;
  546.                                          Char_Delay : INTEGER;
  547.                                          EOS_Delay  : INTEGER  );
  548.  
  549. (*----------------------------------------------------------------------*)
  550. (*                                                                      *)
  551. (*     Procedure:  Async_Send_String_With_Delays                        *)
  552. (*                                                                      *)
  553. (*     Purpose:    Sends string out over communications port with       *)
  554. (*                 specified delays for each character and at the       *)
  555. (*                 end of the string.                                   *)
  556. (*                                                                      *)
  557. (*     Calling Sequence:                                                *)
  558. (*                                                                      *)
  559. (*        Async_Send_String_With_Delays( S          : AnyStr ;          *)
  560. (*                                       Char_Delay : INTEGER;          *)
  561. (*                                       EOS_Delay  : INTEGER );        *)
  562. (*                                                                      *)
  563. (*           S          --- String to send                              *)
  564. (*           Char_Delay --- Number of milliseconds to delay after       *)
  565. (*                          sending each character                      *)
  566. (*           EOS_Delay  --- Number of milleseconds to delay after       *)
  567. (*                          sending last character in string            *)
  568. (*                                                                      *)
  569. (*     Calls:  Async_Send                                               *)
  570. (*             Async_Send_String                                        *)
  571. (*             Length                                                   *)
  572. (*             Delay                                                    *)
  573. (*                                                                      *)
  574. (*     Remarks:                                                         *)
  575. (*                                                                      *)
  576. (*        This routine is useful when writing routines to perform       *)
  577. (*        non-protocol uploads.  Many computer systems require delays   *)
  578. (*        between receipt of characters for correct processing.  The    *)
  579. (*        delay for end-of-string usually applies when the string       *)
  580. (*        represents an entire line of a file.                          *)
  581. (*                                                                      *)
  582. (*        If delays are not required, Async_Send_String is faster.      *)
  583. (*        This routine will call Async_Send_String is no character      *)
  584. (*        delay is to be done.                                          *)
  585. (*                                                                      *)
  586. (*----------------------------------------------------------------------*)
  587.  
  588. VAR
  589.    I : INTEGER;
  590.  
  591. BEGIN  (* Async_Send_String_With_Delays *)
  592.  
  593.    IF Char_Delay <= 0 THEN
  594.       Async_Send_String( S )
  595.    ELSE
  596.       FOR I := 1 TO LENGTH( S ) DO
  597.          BEGIN
  598.             Async_Send( S[I] );
  599.             Delay( Char_Delay );
  600.          END;
  601.  
  602.    IF EOS_Delay > 0 THEN Delay( EOS_Delay );
  603.  
  604. END    (* Async_Send_String_With_Delays *);
  605.  
  606. (*----------------------------------------------------------------------*)
  607. (*      Async_Percentage_Used --- Report Percentage Buffer Filled       *)
  608. (*----------------------------------------------------------------------*)
  609.  
  610. FUNCTION Async_Percentage_Used : REAL;
  611.  
  612. (*----------------------------------------------------------------------*)
  613. (*                                                                      *)
  614. (*     Function:   Async_Percent_Used                                   *)
  615. (*                                                                      *)
  616. (*     Purpose:    Reports percentage of com buffer currently filled    *)
  617. (*                                                                      *)
  618. (*     Calling Sequence:                                                *)
  619. (*                                                                      *)
  620. (*        Percentage := Async_Percentage_Used : Real;                   *)
  621. (*                                                                      *)
  622. (*           Percentage gets how much of buffer is filled;              *)
  623. (*           value goes from 0.0 (empty) to 1.0 (totally full).         *)
  624. (*                                                                      *)
  625. (*     Calls:  None                                                     *)
  626. (*                                                                      *)
  627. (*     Remarks:                                                         *)
  628. (*                                                                      *)
  629. (*       This routine is helpful when incorporating handshaking into    *)
  630. (*       a communications program.  For example, assume that the host   *)
  631. (*       computer uses the XON/XOFF (DC1/DC3) protocol.  Then the       *)
  632. (*       PC program should issue an XOFF  to the host when the value    *)
  633. (*       returned by Async_Percentage_Used > .75 or so.  When the       *)
  634. (*       utilization percentage drops below .25 or so, the PC program   *)
  635. (*       should transmit an XON.                                        *)
  636. (*                                                                      *)
  637. (*----------------------------------------------------------------------*)
  638.  
  639. BEGIN (* Async_Percentage_Used *)
  640.  
  641.    Async_Percentage_Used := Async_Buffer_Used / ( Async_Buffer_Size + 1 );
  642.  
  643. END   (* Async_Percentage_Used *);
  644.  
  645. (*----------------------------------------------------------------------*)
  646. (*     Async_Purge_Buffer --- Purge communications input buffer         *)
  647. (*----------------------------------------------------------------------*)
  648.  
  649. PROCEDURE Async_Purge_Buffer;
  650.  
  651. (*----------------------------------------------------------------------*)
  652. (*                                                                      *)
  653. (*     Procedure:  Async_Purge_Buffer                                   *)
  654. (*                                                                      *)
  655. (*     Purpose:    Purges communications input buffer                   *)
  656. (*                                                                      *)
  657. (*     Calling Sequence:                                                *)
  658. (*                                                                      *)
  659. (*        Async_Purge_Buffer;                                           *)
  660. (*                                                                      *)
  661. (*     Calls:  Async_Receive                                            *)
  662. (*                                                                      *)
  663. (*----------------------------------------------------------------------*)
  664.  
  665. VAR
  666.    C: CHAR;
  667.    L: INTEGER;
  668.  
  669. BEGIN  (* Async_Purge_Buffer *)
  670.  
  671.    L     := 10000 DIV Async_Baud_Rate;
  672.  
  673.    IF L <= 0 THEN
  674.       L := 3;
  675.  
  676.    REPEAT
  677.       DELAY( L )
  678.    UNTIL ( NOT Async_Receive( C ) );
  679.  
  680. END    (* Async_Purge_Buffer *);
  681.  
  682. (*----------------------------------------------------------------------*)
  683. (*          Async_Peek --- Peek ahead in communications buffer          *)
  684. (*----------------------------------------------------------------------*)
  685.  
  686. FUNCTION Async_Peek( Nchars : INTEGER ) : CHAR;
  687.  
  688. (*----------------------------------------------------------------------*)
  689. (*                                                                      *)
  690. (*     Function:   Async_Peek                                           *)
  691. (*                                                                      *)
  692. (*     Purpose:    Peeks ahead in comm buffer                           *)
  693. (*                                                                      *)
  694. (*     Calling Sequence:                                                *)
  695. (*                                                                      *)
  696. (*        Ch := Async_Peek( NChars: INTEGER) : CHAR;                    *)
  697. (*                                                                      *)
  698. (*           NChars --- # of characters to peek ahead                   *)
  699. (*           Ch     --- returned (peeked) character                     *)
  700. (*                                                                      *)
  701. (*     Calls:  None                                                     *)
  702. (*                                                                      *)
  703. (*----------------------------------------------------------------------*)
  704.  
  705. VAR
  706.    I: INTEGER;
  707.  
  708. BEGIN (* Async_Peek *)
  709.  
  710.    I := ( Async_Buffer_Tail + NChars ) MOD Async_Buffer_Size;
  711.  
  712.    IF ( I > Async_Buffer_Head ) THEN
  713.       Async_Peek := CHR( 0 )
  714.    ELSE
  715.       Async_Peek := Async_Buffer_Ptr^[ I ];
  716.  
  717. END   (* Async_Peek *);
  718.  
  719. (*----------------------------------------------------------------------*)
  720. (*         Async_Setup_Port --- Setup port address and IRQ line         *)
  721. (*----------------------------------------------------------------------*)
  722.  
  723. PROCEDURE Async_Setup_Port( ComPort       : INTEGER;
  724.                             Base_Address  : INTEGER;
  725.                             IRQ_Line      : INTEGER;
  726.                             RS_232_Base   : INTEGER );
  727.  
  728. (*----------------------------------------------------------------------*)
  729. (*                                                                      *)
  730. (*     Procedure:  Async_Setup_Port                                     *)
  731. (*                                                                      *)
  732. (*     Purpose:    Sets up port address and IRQ line                    *)
  733. (*                                                                      *)
  734. (*     Calling Sequence:                                                *)
  735. (*                                                                      *)
  736. (*        Async_Setup_Port( ComPort       : INTEGER;                    *)
  737. (*                          Base_Address  : INTEGER;                    *)
  738. (*                          IRQ_Line      : INTEGER;                    *)
  739. (*                          RS_232_Base   : INTEGER );                  *)
  740. (*                                                                      *)
  741. (*           ComPort      --- which port (1 though MaxComPorts)         *)
  742. (*           Base_Address --- Base address of port                      *)
  743. (*           IRQ_Line     --- IRQ line for interrupts for port          *)
  744. (*           RS_232_Base  --- RS 232 base address for port              *)
  745. (*                                                                      *)
  746. (*     Calls:  None                                                     *)
  747. (*                                                                      *)
  748. (*----------------------------------------------------------------------*)
  749.  
  750. BEGIN  (* Async_Setup_Port *)
  751.  
  752.    IF ( ( ComPort > 0 ) AND ( ComPort <= MaxComPorts ) ) THEN
  753.       BEGIN
  754.          Com_Base [ComPort] := Base_Address;
  755.          Com_Irq  [ComPort] := IRQ_Line;
  756.          Com_RS232[ComPort] := RS_232_Base;
  757.       END;
  758.  
  759. END    (* Async_Setup_Port *);
  760.  
  761. (*----------------------------------------------------------------------*)
  762. (*         Async_Release_Buffers --- Release buffers for serial ports   *)
  763. (*----------------------------------------------------------------------*)
  764.  
  765. PROCEDURE Async_Release_Buffers;
  766.  
  767. (*----------------------------------------------------------------------*)
  768. (*                                                                      *)
  769. (*     Procedure:  Async_Release_Buffers;                               *)
  770. (*                                                                      *)
  771. (*     Purpose:    Releases send and receive buffers                    *)
  772. (*                                                                      *)
  773. (*     Calling Sequence:                                                *)
  774. (*                                                                      *)
  775. (*        Async_Release_Buffers;                                        *)
  776. (*                                                                      *)
  777. (*     Calls:  None                                                     *)
  778. (*                                                                      *)
  779. (*----------------------------------------------------------------------*)
  780.  
  781. BEGIN  (* Async_Release_Buffers *)
  782.  
  783.                              (* If port open, close it down first.  *)
  784.    IF Async_Open_Flag THEN
  785.       Async_Close( FALSE );
  786.  
  787.    FREEMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  788.    FREEMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  789.  
  790. END    (* Async_Release_Buffers *);
  791.  
  792. (*----------------------------------------------------------------------*)
  793. (*   Async_Flush_Output_Buffer --- Flush output buffer for serial port  *)
  794. (*----------------------------------------------------------------------*)
  795.  
  796. PROCEDURE Async_Flush_Output_Buffer;
  797.  
  798. (*----------------------------------------------------------------------*)
  799. (*                                                                      *)
  800. (*     Procedure:  Async_Flush_Output_Buffer;                           *)
  801. (*                                                                      *)
  802. (*     Purpose:    Flushes output buffer for serial port.               *)
  803. (*                                                                      *)
  804. (*     Calling Sequence:                                                *)
  805. (*                                                                      *)
  806. (*        Async_Flush_Output_Buffer;                                    *)
  807. (*                                                                      *)
  808. (*     Calls:  None                                                     *)
  809. (*                                                                      *)
  810. (*----------------------------------------------------------------------*)
  811.  
  812. BEGIN  (* Async_Flush_Output_Buffer *)
  813.  
  814.    Async_OBuffer_Head  := Async_OBuffer_Tail;
  815.    Async_OBuffer_Used  := 0;
  816.  
  817. END    (* Async_Flush_Output_Buffer *);
  818.  
  819. (*----------------------------------------------------------------------*)
  820. (*   Async_Drain_Output_Buffer --- Wait for output buffer to drain      *)
  821. (*----------------------------------------------------------------------*)
  822.  
  823. PROCEDURE Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );
  824.  
  825. (*----------------------------------------------------------------------*)
  826. (*                                                                      *)
  827. (*     Procedure:  Async_Drain_Output_Buffer;                           *)
  828. (*                                                                      *)
  829. (*     Purpose:    Waits for output buffer to drain.                    *)
  830. (*                                                                      *)
  831. (*     Calling Sequence:                                                *)
  832. (*                                                                      *)
  833. (*        Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );         *)
  834. (*                                                                      *)
  835. (*           Max_Wait_Time --- Maximum # of seconds to wait for         *)
  836. (*                             output buffer to drain.                  *)
  837. (*                                                                      *)
  838. (*     Calls:  None                                                     *)
  839. (*                                                                      *)
  840. (*----------------------------------------------------------------------*)
  841.  
  842. VAR
  843.    T1 : REAL;
  844.  
  845. BEGIN  (* Async_Drain_Output_Buffer *)
  846.  
  847.    T1 := TimeOfDay;
  848.  
  849.    WHILE( ( Async_OBuffer_Head <> Async_OBuffer_Tail    ) AND
  850.           ( TimeDiff( T1 , TimeOfDay ) <= Max_Wait_Time )     ) DO
  851.       GiveAwayTime( 1 );
  852.  
  853. END    (* Async_Drain_Output_Buffer *);
  854.